import dayjs from "dayjs";
import { generateUniqueTimestamp } from "@src/utils/common";

/** 定义消息类型 */
export interface BackgroundMainContentMsg {
  type: 'HEARTBEAT' | 'B_SAVEDATA' | 'RESPONSE' | 'ah_ebt_gd',
  timestamp: number,
  msgId?: string,
  payload: Record<string,any>
}

export const portNameList = ['backgroundMainContentChannel', 'optionsToBackground']

class MsgFromToContent {
  // 定义 Port 映射，key 为 portName
  private activePorts: Record<string, chrome.runtime.Port> = {};

  private portIntervals: Record<string, Array<ReturnType<typeof setInterval>>> = {};

  private pendingRequests: Record<string, Record<string, (response: any) => void>> = {};

  constructor(){
    // this.initListen()
  }

  clearConnect = (portName:string) => {
    Object.values(this.pendingRequests[portName] || {})?.forEach((resolve) => resolve(null)); // 取消所有未完成的请求
    delete this.activePorts[portName]; // 移除已断开的连接

    this.portIntervals[portName]?.forEach(val => clearInterval(val))
    delete this.portIntervals[portName]
  }

  initListen = () => {
    // 监听连接
    chrome.runtime.onConnect.addListener(this.connectListen);
  }

  connectListen = (port:chrome.runtime.Port) => {
    if (!portNameList.includes(port.name)) return;

    const {name} = port
    // 确保 port.sender.tab 存在
    const tabId = port.sender?.tab?.id;
    if (!tabId) return;
    // 清楚旧的connect
    this.clearConnect(name)

    console.log(`onConnect portName: ${name}`);
    this.activePorts[name] = port;

    // 监听 content script 发送的消息
    port.onMessage.addListener((message: BackgroundMainContentMsg) => this.onMsgListen(name, message));

    // 监听断开事件
    port.onDisconnect.addListener(() => this.onDisconnect(name));
    
    this.sendHeartBeat(port)
  }

  /** 处理来自所有页面的消息 */
  onMsgListen = (portName:string, message: BackgroundMainContentMsg) => {
    switch(portName) {
      case portNameList[0]: {
        this.backgroundMainContentChannelOnMsg(message)
        break;
      }
      default:
        console.error('portName不在portNameList中')
        break;
    }
  }

  sendHeartBeat = (port:chrome.runtime.Port) => {
    if(!this.portIntervals[port.name]) this.portIntervals[port.name] = []

    const message:BackgroundMainContentMsg = {
      type: 'HEARTBEAT',
      timestamp: Date.now(),
      payload:{portName:port.name}
    }
    
    const intervalId = setInterval(() => {
      console.log(`${port.name} sendHeartBeat`)
      this.sendMsgToMain(message);
    }, 25*1000)

    this.portIntervals[port.name].push(intervalId)
  }

  /** 应用于所有页面的连接 */
  onDisconnect = (portName:string) => {
    console.log(`${portName} 断开心跳连接`);
    this.clearConnect(portName)
  }

  /** 只处理来自主系统的content script的消息 */
  backgroundMainContentChannelOnMsg = async (message: BackgroundMainContentMsg) => {
    const {type, timestamp, payload, msgId} = message

    if(msgId && this.pendingRequests?.[portNameList[0]]?.[msgId]) {
      return this.pendingRequests[portNameList[0]][msgId](payload)
    }

    switch(type) {
      case 'HEARTBEAT': {
        console.log(`收到 tab ${portNameList[0]} 心跳: 时间 ${dayjs(timestamp).format('YYYY-MM-DD HH:mm:ss')}`);
        break;
      }
      default:break;
    }
  }

  /** 发送消息到Background */
  sendMsgToMain = (message:Omit<BackgroundMainContentMsg,'timestamp'> & {timestamp?:number}) => {
    const port = this.activePorts[portNameList[0]]
    if(!port) return console.error(`${portNameList[0]} 不存在`)
    
    message.timestamp = Date.now()
    port.postMessage(message);
  }

  /** 发送消息到Background */
  sendAsyncMsgToMain = async (message:Omit<BackgroundMainContentMsg,'timestamp'>) => {
    const port = this.activePorts[portNameList[0]]
    if(!port) return console.error(`${portNameList[0]} 不存在`)
    
    const msgId = generateUniqueTimestamp()
    message.msgId = msgId

    if(!this.pendingRequests[portNameList[0]]) this.pendingRequests[portNameList[0]] = {}

    return new Promise((resolve) => {
      this.pendingRequests[portNameList[0]][msgId] = resolve

      this.sendMsgToMain(message)
    })
  }

}

export const MsgToContent = new MsgFromToContent
